package ms.unicorn.reasoning.optimize;

import java.util.ArrayList;
import java.util.BitSet;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;

public class DAT extends ArrayList<AnnotatedAlternative> {

	private static final long serialVersionUID = 1L;

	
	public DAT() {
		
	}
	
	public DAT(int cap) {
		super(cap);
	}
	
	public DAT(DAT dat) {
		super(dat.size());
		super.addAll(dat);
	}
	
	public DAT applyProbability(float p, String possibility) {
		DAT dat = new DAT(this.size());
		for (AnnotatedAlternative alt: this)
			dat.add(new AnnotatedAlternative(alt.nodes, alt.mb * p, 1 - (1 - alt.rr) * p, possibility));
		return dat;
	}
	
	@Override
	public boolean add(AnnotatedAlternative e) {
		int idx = Collections.binarySearch(this, e);
		if (idx >= 0) return false;
		idx = -(idx + 1);
		// look for an alternative that e subsumes
		for (int i = idx-1; i >=0; i--)
			if (get(i).subsumes(e, true)) return false;
		// look for an alternative that subsumes e
		for (int i = size()-1; i >= idx; i--)
			if (e.subsumes(get(i), true))
				remove(i);
		super.add(idx, e);
		return true;
	}
	
	@Override
 	public String toString() {
		String s = "[";
		for(AnnotatedAlternative alt: this)
			s += alt.toString() + " ";
		s += "]";
		return s;
	}
	
	public static DAT concat(DAT a, DAT b) {		
		DAT result = new DAT( (a!= null ? a.size() : 0)+ (b!=null ? b.size(): 0));
		if (a != null) result.addAll(a);
		if (b != null) result.addAll(b);
			
		result.filter();
		
		return result;
	}
	
	public static DAT join(DAT a, DAT b) {
		if (a == null) return new DAT(b);
		if (b == null) return new DAT(a);
		
		DAT result = new DAT(Math.max(a.size(), b.size()));

		for(AnnotatedAlternative ae: a)
			for (AnnotatedAlternative be: b) {
				AnnotatedAlternative node = AnnotatedAlternative.join(ae,  be);
				result.add(node);
			}
		
		
		//result.filter();
		return result;
	}
	
	private void filter() {
		AnnotatedAlternative alts[] = this.toArray(new AnnotatedAlternative[size()]);
		for (int i = 0; i < alts.length - 1; i++) 
			if (contains(alts[i])) 
				for (int j = i+1; j < alts.length; j++) 
					if (contains(alts[j])) {
						if (alts[i].subsumes(alts[j], true )) {
							remove(alts[i]);
							break;
						} else if (alts[j].subsumes(alts[i], true))
							remove(alts[j]);
					}
	}

	public boolean addAlternative(FDNode node, int mb, int rr) {
		AnnotatedAlternative alt = new AnnotatedAlternative(node, mb, rr);
		return add(alt);
	}

}
